package com.budwk.app.waterquality.services.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.services.SysConfigService;
import com.budwk.app.utils.PoiUtil;
import com.budwk.app.waterquality.component.CommonComponent;
import com.budwk.app.waterquality.component.WaterQualityComponent;
import com.budwk.app.waterquality.config.AppException;
import com.budwk.app.waterquality.enums.WaterQEnum;
import com.budwk.app.waterquality.models.ScoreInfo;
import com.budwk.app.waterquality.models.WaterQualityIndicator;
import com.budwk.app.waterquality.services.AppealrecordService;
import com.budwk.app.waterquality.services.WaterQualityIndicatorService;
import com.budwk.app.waterquality.vo.ParamProblemVo;
import com.budwk.app.waterquality.vo.WaterQualityCommonVo;
import com.budwk.app.waterquality.vo.WaterQualityVo;
import com.budwk.starter.common.page.Pagination;
import com.budwk.starter.database.service.BaseServiceImpl;
import com.budwk.starter.storage.StorageServer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.xssf.streaming.SXSSFCell;
import org.apache.poi.xssf.streaming.SXSSFRow;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@IocBean(args = {"refer:dao"})
@Slf4j
public class WaterQualityIndicatorServiceImpl extends BaseServiceImpl<WaterQualityIndicator> implements WaterQualityIndicatorService {
    public WaterQualityIndicatorServiceImpl(Dao dao) {
        super(dao);
    }

    @Inject
    private AppealrecordService appealrecordService;
    @Inject
    private StorageServer storageServer;
    @Inject
    private SysConfigService sysConfigService;

    @Override
    public Pagination listByPage(WaterQualityCommonVo reqVo) {
        Cnd cnd = WaterQualityComponent.bulidQueryCondition(reqVo);
        return this.listPage(reqVo.getPageNo(), reqVo.getPageSize(), cnd);
    }

    @Override
    public WaterQualityIndicator addIndicator(WaterQualityIndicator indicator) {
        // 1 参数校验

        // 2 参数初始化
        WaterQualityComponent.initAddIndicator(indicator);
        this.insert(indicator);
        return indicator;
    }

    @Override
    public void abnormalMarking(ParamProblemVo problemVo) {
        // 1 参数校验
        WaterQualityComponent.checkAbnormalMarkingParam(problemVo);
        // 2 业务代码处理
        WaterQualityIndicator indicator = this.fetch(problemVo.getId());
        if (indicator == null) {
            throw new AppException("数据不存在！");
        }
        WaterQualityVo w = JSONObject.parseObject(indicator.getWaterQualityData(), WaterQualityVo.class);
        List<ParamProblemVo> waterParam = w.getWaterParam();
        Optional<ParamProblemVo> optional = waterParam.stream().filter(e -> e.getField().equals(problemVo.getField())).findFirst();
        if (optional.isEmpty()) {
            throw new AppException("数据编码不能存在！");
        }
        // 修改当前数据 记录异常
        ParamProblemVo p = optional.get();
        p.setIsException(problemVo.getIsException());
        w.setWaterParam(waterParam);
        Sys_user user = CommonComponent.getCurrentUser();
        indicator.setWaterQualityData(JSONObject.toJSONString(w)).setUpdateDate(LocalDateTime.now()).setUpdateId(user.getId());
        this.updateIgnoreNull(indicator);
        appealrecordService.saveAbnormalMarking(indicator, p);
    }

    @Override
    public String downStatReport(WaterQualityCommonVo reqVo, HttpServletResponse response) throws IOException {
        XSSFWorkbook workbook = new XSSFWorkbook(PoiUtil.getInputStream("/formTemplate/file/waterQualityIndicator/waterFormsTemplate.xlsx"));
        SXSSFWorkbook book = new SXSSFWorkbook(workbook, 100);
        Cnd cnd = WaterQualityComponent.bulidQueryCondition(reqVo);
        List<WaterQualityIndicator> list = this.query(cnd);
        if (CollectionUtil.isEmpty(list)) {
            return PoiUtil.getDownFileUrl(System.currentTimeMillis() + ".xlsx", book, response);
        }
        CellStyle cellStyle = PoiUtil.getCellStyle(book);
        SXSSFSheet sheet = book.getSheetAt(0);
        List<List<String>> params = buildContent(list);
        int rowIndex = 2;
        for (List<String> param : params) {
            SXSSFRow row = sheet.createRow(rowIndex);
            int cellIndex = 0;
            for (String value : param) {
                SXSSFCell cell = row.createCell(cellIndex);
                cell.setCellValue(value);
                cell.setCellStyle(cellStyle);
                cellIndex ++;
            }
            rowIndex ++;
        }
        String downFileUrl = PoiUtil.getDownFileUrl(System.currentTimeMillis() + ".xlsx", book, response);
        log.info("res down path: {}", "http:127.0.0.1:18285/api" + downFileUrl);
        return downFileUrl;
    }


    private List<List<String>> buildContent(List<WaterQualityIndicator> list) {

        List<List<String>> datas = new ArrayList<>();
        for (WaterQualityIndicator w : list) {
            List<String> params = new ArrayList<>();
            String waterQualityData = w.getWaterQualityData();
            if (StringUtils.isEmpty(waterQualityData)) {
                continue;
            }
            WaterQualityVo waterQualityVo = JSONObject.parseObject(waterQualityData, WaterQualityVo.class);
            params.add(waterQualityVo.getSTCD());
            params.add(waterQualityVo.getSTNM());
            params.add(waterQualityVo.getLYNM());
            params.add(waterQualityVo.getSPT());
            params.add(waterQualityVo.getFXT());
            // 水位及其他参数
            getFiledValue(WaterQEnum.Z.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.Q.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.WT.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.PH.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.DOX.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.COMN.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.CODCR.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.BOD5.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.NH3N.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.TP.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.TN.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.CU.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.ZN.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.F.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.SE.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.ARS.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.HG.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.CD.getField(), waterQualityVo.getWaterParam(), params);
            getFiledValue(WaterQEnum.CR6.getField(), waterQualityVo.getWaterParam(), params);

            datas.add(params);
        }
        return datas;
    }

    private static void getFiledValue(String filed, List<ParamProblemVo> waterParam, List<String> params) {
        if (CollectionUtil.isEmpty(waterParam)) {
            params.add("-");
            return;
        }
        Optional<ParamProblemVo> first = waterParam.stream().filter(e -> e.getField().equals(filed)).findFirst();
        if (first.isEmpty()) {
            params.add("-");
            return;
        }
        params.add(first.get().getValue());
    }
}
